package org.qloudgen.txn.dilithium.cluster.monitor;

import java.io.Serializable;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.qloudgen.txn.dilithium.cluster.beans.Cluster;
import org.qloudgen.txn.dilithium.cluster.beans.NodeInfo;
import org.qloudgen.txn.dilithium.cluster.common.CommonValues;
import org.qloudgen.txn.dilithium.cluster.common.ShellExec;

public class Monitor implements Serializable{

	private static final long serialVersionUID = 1L;

	static Log log = LogFactory.getLog(Monitor.class);
	
	private Cluster cluster;
	private StringBuffer monitorInfo = new StringBuffer();
	private List<NodeInfo> nodes;

	public Monitor(Cluster cluster){
		this.setCluster(cluster);
	}
	
	public void execMonitor(){
		
		int ret = ShellExec.getMonitorInfo(this.getCluster(), this.getMonitorInfo());
		
		if (ret !=0 ) {
			log.error(CommonValues.ERROR_GET_MONITOR_INFO + " for cluster_id : " + this.getCluster().getClusterID());
			return;
		}
		
		parseInfo();
		
	}
	
	private void parseInfo(){
		
		String[] infos = this.getMonitorInfo().toString().split("\n");
		
		if (infos == null) return;
		
		nodes.clear();
		for (int i=0; i< infos.length; i++){
			
			if (infos[i].startsWith("Running")||infos[i].startsWith("Not running")) {
				NodeInfo nodeInfo = parseNodeInfo(infos[i]);
				
				if (nodeInfo != null)
					nodes.add(nodeInfo);
			}
		}
		
		this.getMonitorInfo().setLength(0);
	}
	
	private NodeInfo parseNodeInfo(String info){
		
		if (info == null) return null;

		NodeInfo nodeInfo = new NodeInfo();
		
		//find node type ,node name,node ip ,node port, node dirl
        Matcher matcher = Pattern.compile("(?<=(:|type:|name:|host:|port:))(.+?)(?=-|  )").matcher(":"+info+"  ");
        
        int i = 0;
		while (matcher.find()){
			
			String value = matcher.group();
			switch(i) {
				case 0: nodeInfo.setNodeStatus(value);
				case 1: nodeInfo.setNodeType(value);
				case 2: nodeInfo.setNodeName(value);
				case 3: nodeInfo.setNodeIp(value);
				case 4: nodeInfo.setNodePort(value);
			}

			i++;
		}
		
		return nodeInfo;
	}

	public StringBuffer getMonitorInfo() {
		return monitorInfo;
	}

	public List<NodeInfo> getNodes() {
		return nodes;
	}

	public void setNodes(List<NodeInfo> nodes) {
		this.nodes = nodes;
	}

	public Cluster getCluster() {
		return cluster;
	}

	public void setCluster(Cluster cluster) {
		this.cluster = cluster;
	}

	
}
